/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.cloudfarming.client.sensor.greenseeker;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import nl.cloudfarming.client.logging.AppLogFactory;
import nl.cloudfarming.client.logging.AppLogger;
import nl.cloudfarming.client.sensor.SensorProcessorProvider;
import nl.cloudfarming.client.util.FilePickerUtil;
import nl.cloudfarming.client.util.MD5Sum;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;

/**
 * Processor for greenseeker data
 *
 * @author Gerben Feenstra
 */
@ServiceProvider(service = SensorProcessorProvider.class)
public class GreenseekerProcessorProvider implements SensorProcessorProvider {

    private static final AppLogger LOG = AppLogFactory.getLogger(GreenseekerProcessorProvider.class);
    private static final String LOGKEY_FILE_ALREADY_IMPORTED = "message.info.file_alread_imported";
    private final String formatDescription = NbBundle.getMessage(this.getClass(), "greenseeker.processor.formatdescription", FilePickerUtil.getFileFilterTypeString(Arrays.asList(getSupportedExtentions())));

    // Is there a better place then here? Header length is also specified in GreenseekerFileProcessor
    private static final int HEADER_LENGTH_NORMAL = 480;
    private static final int HEADER_LENGTH_BORNE = 672;

    @Override
    public String[] getSupportedExtentions() {
        return new String[]{".dbf"};
    }

    @Override
    public boolean isSupported(File sensorFile) {
        String fileExtension = sensorFile.getName().substring(sensorFile.getName().lastIndexOf("."));

        // 1: Check extension
        if(!Arrays.asList(getSupportedExtentions()).contains(fileExtension)){
            return false;
        }
        // 2: Check header length
        try {
            FileInputStream fstream = new FileInputStream(sensorFile);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine = br.readLine();
            if(HEADER_LENGTH_NORMAL != strLine.length() && HEADER_LENGTH_BORNE != strLine.length()){
                return false;
            }
            in.close();
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
        return true;
    }

    @Override
    public boolean isValid(File sensorFile) {
        try {
            String checkSum = MD5Sum.getHex(MD5Sum.createChecksum(new FileInputStream(sensorFile)));
            String fileName = sensorFile.getName();
            if (new GreenseekerServiceImpl().findFileByNameAndChecksum(fileName, checkSum) == null) {
                return true;
            } else {
                LOG.info(LOGKEY_FILE_ALREADY_IMPORTED, fileName);
            }
        } catch (NoSuchAlgorithmException ex) {
            LOG.error(ex.getMessage());
        } catch (IOException ex) {
            LOG.error(ex.getMessage());
        }
        return false;
    }

    @Override
    public String getFormatDescription() {
        return this.formatDescription;
    }

    /*
     * Provide the right GreenseekerFileProcessor instance 
     * 
     * TODO: Exception handling
     */
    @Override 
    public GreenseekerFileProcessor getProcessor(File sensorFile) {

        // Header normal= 481, borne = 672, use shortest to determine which filetype it is.
        final byte[] header = new byte[HEADER_LENGTH_NORMAL];
            
        // Determine which type of greenseeker sensorfile we need to process
        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(sensorFile));
            bis.read(header);


        } catch (FileNotFoundException ex) {
                Exceptions.printStackTrace(ex);
        } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
        } finally {
            try {
                bis.close();
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
        
        if (new String(header).contains("RED_54") && new String(header).contains("NIR_54")){
            return new GreenseekerFileProcessorBorne(sensorFile);
        }
        else{
            return new GreenseekerFileProcessorNormal(sensorFile);
        }
                    
    }
}
